using System;
using System.Reflection;
using Agatha.Common.InversionOfControl;
using Agatha.Common.WCF;

namespace Agatha.Common
{
	public class ClientConfiguration
	{
		private readonly Assembly requestsAndResponsesAssembly;
		private readonly IContainer container;

		public Type AsyncRequestDispatcherImplementation { get; set; }
		public Type AsyncRequestDispatcherFactoryImplementation { get; set; }
		public Type RequestProcessorImplementation { get; set; }
		public Type ContainerImplementation { get; private set; }

		public ClientConfiguration(Assembly requestsAndResponsesAssembly, IContainer container)
		{
			this.requestsAndResponsesAssembly = requestsAndResponsesAssembly;
			this.container = container;
			SetDefaultImplementations();
		}

 		public ClientConfiguration(Assembly requestsAndResponsesAssembly, Type containerImplementation)
		{
			this.requestsAndResponsesAssembly = requestsAndResponsesAssembly;
			ContainerImplementation = containerImplementation;
			SetDefaultImplementations();
		}

		private void SetDefaultImplementations()
		{
			AsyncRequestDispatcherImplementation = typeof(AsyncRequestDispatcher);
			AsyncRequestDispatcherFactoryImplementation = typeof(AsyncRequestDispatcherFactory);
			RequestProcessorImplementation = typeof(AsyncRequestProcessorProxy);
		}

		public void Initialize()
		{
			IoC.Container = container ?? (IContainer)Activator.CreateInstance(ContainerImplementation);
			IoC.Container.RegisterInstance(this);
			IoC.Container.Register(typeof(IAsyncRequestProcessor), RequestProcessorImplementation, Lifestyle.Transient);
			IoC.Container.Register(typeof(IAsyncRequestDispatcher), AsyncRequestDispatcherImplementation, Lifestyle.Transient);
			IoC.Container.Register(typeof(IAsyncRequestDispatcherFactory), AsyncRequestDispatcherFactoryImplementation, Lifestyle.Singleton);
			RegisterRequestAndResponseTypes();
		}

		private void RegisterRequestAndResponseTypes()
		{
			KnownTypeProvider.RegisterDerivedTypesOf<Request>(requestsAndResponsesAssembly);
			KnownTypeProvider.RegisterDerivedTypesOf<Response>(requestsAndResponsesAssembly);
		}
	}
}